home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 013 / move13.arc / MOVE.ASM < prev    next >
Encoding:
Assembly Source File  |  1986-04-10  |  32.3 KB  |  1,166 lines

  1.     page 60,132
  2.  
  3.     Title MOVE.COM    Ver 1.3 - By Jay B. Harlow - 10 Apr 86
  4.  
  5. comment /****************************************************************
  6.      *                                *
  7.      *                MOVE.COM                *
  8.      *                                *
  9.      *            By Jay B. Harlow            *
  10.      *                                *
  11.      *                10 Apr 86                *
  12.      *                                *
  13.      *   This is a simple program to move files from one directory    *
  14.      * to another directory, it works both on one disk and across    *
  15.      * more than one disk.  Move is easier put works almost        *
  16.      * like COPY & DELETE, except when its on the same disk it    *
  17.      * simple does a rename function saving on disk space.        *
  18.      *   Due to DOS, trying to move something to or from a device    *
  19.      * simple does not work, so don't try it.            *
  20.      *                                 *
  21.      * Ver 1.0                            *
  22.      *   initial program to rename files from one directory to    *
  23.      *   to a new directory, works across disks also        *
  24.      *                                *
  25.      * Ver 1.1 added                        *
  26.      *   attempt to correct a bug that would delete files when    *
  27.      *   renameing to the same name in one directory        *
  28.      *   intercept Ctrl-C                        *
  29.      *                                *
  30.      * Ver 1.2 added                        *
  31.      *   Version fixed a bug that would delete files when        *
  32.      * attempting to rename file to the same name            *
  33.      *   Lets user know if gave too many or too few parameters    *
  34.      *   Checks diskette space before copying the file across    *
  35.      * diskettes                            *
  36.      *                                *
  37.      * Ver 1.3 added                        *
  38.      *   moved some variables to the stack to make com file smaller    *
  39.      *   added Pause option to simplify 2 disk moves        *
  40.      *                                *
  41.      ****************************************************************/
  42.  
  43.     include 186inst.mac    ; fake a 80186 instruction set
  44.     include char.def    ; define a few character constants
  45.     include dos.mac        ; define info on DOS
  46.  
  47. ; define macros to make working with file size easier
  48.  
  49. sub32    macro des,src        ; subtract 2 32 bit numbers
  50.     mov ax,word ptr src    ; low words
  51.     sub word ptr des,ax    ;    subtract
  52.     mov ax,word ptr src+2    ; high words
  53.     sbb word ptr des+2,ax    ;    subtract
  54. endm
  55.  
  56. add32    macro des,src        ; add 2 32 bit numbers
  57.     mov ax,word ptr src    ; low words
  58.     add word ptr des,ax    ;    add
  59.     mov ax,word ptr src+2    ; high words
  60.     adc word ptr des+2,ax    ;    add
  61. endm
  62.  
  63. ; tell the assembler that we are making a COM file
  64. cseg    segment para public 'CODE'
  65.     assume cs:cseg,ss:cseg,ds:cseg,es:cseg
  66.  
  67. ;   Data
  68.  
  69. ifdef DEBUG            ; allow use of symdeb
  70.     public arglen,arg,entry,dta,desdta
  71. endif                ; simplify debugging
  72.  
  73.     org 80h
  74. arglen    db ?            ; length of command line
  75. arg    db 7fh dup (?)        ; command line from DOS
  76.  
  77.     org 100h
  78. entry:    jmp main        ; skip all the data goto main program
  79.  
  80.     db '  MOVE.COM    Ver 1.3 -  By Jay B. Harlow   -   10 Apr 86',eof
  81.  
  82. dta    dta_type <>        ; set up a dta for dir search of source
  83. desdta    dta_type <>        ; set up a dta for dir search of destination
  84.                 ; used to see if source = destination
  85.  
  86. ifdef DEBUG            ; allow use of symdeb
  87.     public size_buffer,num_moved,help
  88. endif                ; simplify debugging
  89.  
  90. size_buffer dw ?        ; number of bytes in copy buffer
  91. num_moved dw ?            ; the number of files moved
  92.  
  93. help    db lf,lf,cr        ; a short help message
  94.     db '  MOVE.COM  -  Move files',lf,cr
  95.     db lf,cr
  96.     db '   Invoke MOVE ? | [option] source filespec[,destination filespec]'
  97.     db lf,cr,lf,cr
  98.     db '    The filespec is [drive][path][filename]',lf,cr
  99.     db '    If only a drive or path is given all the files in',lf,cr
  100.     db '    That drive or path are moved.',lf,cr
  101.     db lf,cr
  102.     db '    Use the P option to pause before moving files',lf,cr
  103.     db lf
  104.     db '    *** WARNING ***   Do Not Use on devices!',lf,nul
  105.  
  106. ifdef DEBUG            ; allow use of symdeb
  107.     public notfile,noopenin,noopenout,notransfer,no_param
  108.     public movedmsg1,movedmsg2,movedmsg3,lf_cr,global
  109.     public aborted,incorrect_dos,no_room
  110.     public unknown_option,invalid_option,pause_msg
  111. endif                ; simplify debugging
  112.  
  113. ;  used when a source name wasn't found
  114. notfile        db ' not Found.',nul
  115.  
  116. ;  Couldn't open the input file for copy
  117. noopenin    db 'Unable to open File for Input.',nul
  118.  
  119. ;  Couldn't open the output file for copy
  120. noopenout    db 'Unable to open File for Output.',nul
  121.  
  122. ;  Something went wrong didn't get moved
  123. notransfer    db 'Unable to Move File.',nul
  124.  
  125. ;  didn't find any parameters on command line
  126. no_param    db 'Invalid Number of Parameters.',nul
  127.  
  128. ;  first part of string when printing the number of files moved
  129. movedmsg1    db ht,nul
  130.  
  131. ;  second part of string when printing the number of files moved
  132. movedmsg2    db ' File',nul
  133.  
  134. ;  last part of string when printing the number of files moved
  135. movedmsg3    db ' moved.',nul
  136.  
  137. ;  The transfer was aborted Ctrl-C (Ctrl-break) was hit
  138. aborted        db 'Move Aborted.',nul
  139.  
  140. ;  The program is attempting to use wrong DOS Ver
  141. incorrect_dos    db 'Incorrect DOS Ver.',lf,cr
  142.         db '  This program needs 2.0 or higher.',nul
  143.  
  144. ;  there was not enough room on the destination disk
  145. no_room        db 'Insufficiant room.',nul
  146.  
  147. ;  an incorrect option was given
  148. invalid_option    db ' Invalid Option.',nul
  149.  
  150. ;  an incorrect option was given
  151. unknown_option    db ' Unknown Option.',nul
  152.  
  153. ;  used when want ot pause before moving files
  154. pause_msg    db 'Press Any Key to Continue...',nul
  155.  
  156. ;  end of line - New line
  157. lf_cr        db lf,cr,nul
  158.  
  159. ;  where to go if no specific file is given ( a drive or path only )
  160. global        db '*.*',nul
  161. len_global = $ - global
  162.  
  163. ;    ROUTINES
  164.  
  165. jbrk    macro des        ; jump to des if break was hit
  166.     local cont
  167.     test break,-1
  168.     jz cont
  169.         jmp des
  170. cont:
  171. endm
  172.  
  173. ifdef DEBUG            ; allow use of symdeb
  174.     public break,savebreak,_install_break,break_handler,_restore_break
  175. endif                ; simplify debugging
  176.  
  177. break    db 0            ; flag that a Ctrl-C occured
  178. savebreak dd ?            ; someplace save to put old break routine
  179.  
  180. ; routine to intercept Ctrl-C
  181. ; installs the break_handler routine to take care of it
  182.  
  183. install_break macro
  184.     call _install_break
  185. endm
  186.  
  187. _install_break proc near
  188.     push es            ; save
  189.     mov ax,3523h        ; get break vector
  190.     int 21h            ; call DOS
  191.     mov word ptr savebreak,bx    ; save ip of old break routine
  192.     mov word ptr savebreak+2,es    ; save cs of old break routine
  193.     mov ax,2523h        ; set new break vector
  194.     lea dx,break_handler    ; where the new routine is
  195.     int 21h            ; call DOS
  196.     sti            ; allow interupts
  197.     pop es            ; restore
  198.     ret
  199. _install_break endp
  200.  
  201. ; set the break flag to -1 to indicate a Ctrl-C occurred
  202.  
  203. break_handler proc near
  204.     mov cs:break,-1        ; set the break flag
  205.     iret            ; end of interupt
  206. break_handler endp
  207.  
  208. restore_break macro
  209.     call _restore_break
  210. endm
  211.  
  212. ; routine to restore the Ctrl-C handler back to DOS
  213.  
  214. _restore_break proc near
  215.     push ds            ; save
  216.     mov ax,2523h        ; restore break vector
  217.     lds dx,savebreak    ; what old vector was
  218.     int 21h            ; call DOS
  219.     pop ds            ; restore
  220.     ret
  221. _restore_break endp
  222.  
  223. ; takes the word ptr off the stack and uses it to print out
  224. ; an ASCIIZ string
  225.  
  226. printz    macro source
  227.     ifnb <source>
  228.     lea ax,source
  229.     push ax
  230.     endif
  231.     call _printz
  232. endm
  233.  
  234. ifdef DEBUG            ; allow use of symdeb
  235.     public _printz,printz_loop,printz_exit
  236. endif                ; simplify debugging
  237.  
  238. _printz proc near        ; print a ASCIIZ string (path names)
  239.     enter 0,0
  240.     cld            ; ensure left to right
  241.     mov si,word ptr [bp+4]    ; get the parameter off stack
  242. printz_loop:
  243.     lodsb            ; get one char
  244.     cmp al,nul        ; if not last one
  245.     je printz_exit        ;  then
  246.         putchar al        ;    put on screen
  247.         jmp printz_loop    ;    go for another one
  248. printz_exit:            ;  else
  249.     leave            ; exit routine
  250.     ret 2            ; discard parameter
  251. _printz endp
  252.  
  253. println    macro string
  254.     lea ax,string
  255.     push ax
  256.     call _println
  257. endm
  258.  
  259. ifdef DEBUG            ; allow use of symdeb
  260.     public _println
  261. endif                ; simplify debugging
  262.  
  263. _println proc near        ; print out a string ending w/nul
  264. string    equ word ptr [bp+4]
  265.     enter 0,0
  266.     push string
  267.     printz            ; print the string
  268.     printz lf_cr        ; goto newline
  269.     leave
  270.     ret 2
  271. _println endp
  272.  
  273. ; takes an integer (signed word) off the stack and prints it
  274. ; non formatted to the screen
  275.  
  276. printint macro int
  277.     push int
  278.     call _printint
  279. endm
  280.  
  281. ifdef DEBUG            ; allow use of symdeb
  282.     public _printint,not_negative,int_ascii_loop
  283. endif                ; simplify debugging
  284.  
  285. _printint proc near
  286. int    equ word ptr [bp+4]
  287. str    equ byte ptr [bp-6]
  288.     enter 6,0
  289.     cld            ; left to right
  290.     cmp int,0        ; if int < 0
  291.     jnl not_negative    ; then
  292.         putchar '-'        ;   output a negitive sign
  293.         neg int        ;   make it positive
  294. not_negative:
  295.     lea di,str        ; scratch buffer
  296.     mov al,0        ; end of str
  297.     mov cx,6        ; max number of characters
  298.     rep stosb        ; make str nul
  299.     lea di,str+5        ; where the low digit goes
  300.     mov bx,10
  301.     mov ax,int        ; number to print
  302. int_ascii_loop:
  303.         xor dx,dx        ; zero hi word
  304.         div bx        ; int / 10
  305.         add dl,'0'        ; (int mod 10) + '0'
  306.         dec di        ; next char
  307.         mov [di],dl        ; save char
  308.         or ax,ax        ; see if ax is zero
  309.         jnz int_ascii_loop    ; until int is zero
  310.     push di            ; pointer to str
  311.     printz            ; print out str
  312.     leave
  313.     ret 2            ; discard param
  314. _printint endp
  315.  
  316. ; print out the a message telling user number of files moved
  317. ; the number of files is on the stack
  318.  
  319. printmoved macro int
  320.     push int
  321.     call _printmoved
  322. endm
  323.  
  324. ifdef DEBUG            ; allow use of symdeb
  325.     public _printmoved,one
  326. endif                ; simplify debugging
  327.  
  328. _printmoved proc near
  329.     enter 0,0
  330.     printz movedmsg1    ; print first part of message
  331.     printint int        ; print out the integer
  332.     printz movedmsg2    ; middle part of message
  333.     cmp int,1        ; int <> 1
  334.     je one            ; then
  335.         putchar 's'        ;   print an s for syntax
  336. one:
  337.     println movedmsg3    ; finish the message
  338.     leave
  339.     ret 2            ; discard param
  340. _printmoved endp
  341.  
  342. ; routine to check the character in al to see if it is a valid delimeter
  343.  
  344. ifdef DEBUG            ; allow use of symdeb
  345.     public checkdelim,delims
  346. endif                ; simplify debugging
  347.  
  348. ; the set of valid non delimeters (0-delimeter, 1-nondelimeter)
  349.  
  350. delims    db 00000000B,00000000B,00000000B,00000000B
  351.     db 01011111B,11100111B,11111111B,11100001B
  352.     db 11111111B,11111111B,11111111B,11101011B
  353.     db 11111111B,11111111B,11111111B,11111110B
  354.     db 11111111B,11111111B,11111111B,11111111B
  355.     db 11111111B,11111111B,11111111B,11111111B
  356.     db 11111111B,11111111B,11111111B,11111111B
  357.     db 11111111B,11111111B,11111111B,11111111B
  358.  
  359. checkdelim proc near        ; check al is delimeter
  360.     xor bx,bx        ; zero
  361.     mov bl,al        ; char to test
  362.     mov cl,al
  363.     mov al,80h
  364.     and cl,7        ; byte location
  365.     shr al,cl        ; bit location
  366.     mov cl,3
  367.     shr bx,cl        ; byte index
  368.     test delims[bx],al    ; is this bit set?
  369.     ret
  370. checkdelim endp
  371.  
  372. ; skip all of the delimeters in the param string
  373.  
  374. skipdelim macro
  375.     call _skip
  376. endm
  377.  
  378. ifdef DEBUG            ; allow use of symdeb
  379.     public _skip,skiploop,skipexit
  380. endif                ; simplify debugging
  381.  
  382. _skip    proc near        ; skip delimeters in command line string
  383. ; input
  384. ;  AL    -  has the character
  385. ;  SI    -  has the string
  386. ;  CX    -  has the length
  387. ; output
  388. ;  SI    -  updated string ptr
  389. ;  CX    -  updated string length
  390.     jcxz skipexit        ; if char then
  391. skiploop: lodsb            ; get a char
  392.     push cx            ; save count
  393.     call checkdelim        ; while not delimeter
  394.     pop cx            ; restore count
  395.     loope skiploop        ; where found
  396.     je skipexit        ; nothing found
  397.         dec si        ; point to character found
  398.             inc cx        ; count of string
  399. skipexit:
  400.     ret
  401. _skip endp
  402.  
  403. ; save the parameter w/conversion to uppercase
  404.  
  405. savenam macro where
  406.     lea di,where
  407.     call _save
  408. endm
  409.  
  410. ifdef DEBUG            ; allow use of symdeb
  411.     public _save,save_loop,save_char,not_lower,save_exit
  412. endif                ; simplify debugging
  413.  
  414. _save    proc near        ; routine to move token 
  415. ; input
  416. ;  SI - has the string
  417. ;  DI - has the destination
  418. ;  CX - has the length of the string
  419. ; output
  420. ;  SI - updated delimeter left in string
  421. ;  CX - updated
  422.     jcxz save_exit        ; if nothing there
  423. save_loop: lodsb        ; get a char
  424.     push ax            ; save character
  425.     push cx            ; save count
  426.     call checkdelim        ; while not delimeter
  427.     pop cx            ; restore count
  428.     pop ax            ; restore character
  429.     jne save_char        ; if delimeter
  430.         dec si        ;    point to last char
  431.         jmp short save_exit    ; else
  432. save_char:
  433.         cmp al,'a'        ; is it lower case
  434.         jb not_lower
  435.         cmp al,'z'
  436.         ja not_lower
  437.             and al,5fh    ; make upper case
  438. not_lower:
  439.         stosb        ; save the char
  440.         loop save_loop    ; not end of line
  441. save_exit:            ; exit
  442.     mov byte ptr [di],0    ; end of string
  443.     ret
  444. _save    endp
  445.  
  446. checkparam macro param
  447.     lea di,param
  448.     call _checkparam
  449. endm
  450.  
  451. ifdef DEBUG            ; allow use of symdeb
  452.     public _checkparam,checkparam_exit,option,option_bad
  453. endif                ; simplify debugging
  454.  
  455. _checkparam proc near
  456.     push cx
  457.     push si
  458.     cmp byte ptr [di],'/'    ; option can have either forward slash
  459.     je option
  460.     cmp byte ptr [di],'-'    ; or a minus sign as the legal indicator
  461.     je option
  462.     clc            ; flag no option present
  463. checkparam_exit:
  464.     pop si
  465.     pop cx
  466.     ret
  467. option:    cmp byte ptr [di+2],nul ; check option one character only
  468.     jne option_bad
  469.         cmp byte ptr [di+1],'P' ; is it a P
  470.         jne not_p
  471.         println pause_msg ; ask user to press a key
  472.         mov ax,0c07h    ; wait until keypressed
  473.         int 21h
  474.         cmp al,3    ; was Ctrl-C pressed
  475.         stc        ; signal an option 
  476.         jne checkparam_exit
  477.         mov break,-1    ; set the break flag
  478.         stc        ; signal an option 
  479.         jmp checkparam_exit
  480. not_p:
  481.         push di        ; print out the option given
  482.         printz 
  483.         println unknown_option ; tell user its bad
  484.         stc            ; signal an option 
  485.         jmp checkparam_exit
  486. option_bad:
  487.     push di            ; print out the option given
  488.     printz 
  489.     println invalid_option    ; tell user its bad
  490.     stc            ; signal an option 
  491.     jmp checkparam_exit
  492. _checkparam endp
  493.  
  494. ; routine to search a string for a specific character
  495.  
  496. searchchar macro string,char
  497.     mov di,string
  498.     mov al,char
  499.     call _searchchar
  500. endm
  501.  
  502. ifdef DEBUG            ; allow use of symdeb
  503.     public _searchchar,search_next,search_more,search_exit
  504. endif                ; simplify debugging
  505.  
  506. _searchchar proc near        ; see if char in al is in string @ di
  507.     enter 0,0
  508.     push di            ; save index for later
  509.     cld            ; follow string left to right
  510. search_next:
  511.     scasb            ; is this one
  512.     jne search_more        ; than
  513.         stc            ; -1
  514.         sbb di,[bp-2]    ; index into string where found
  515.         mov ax,di        ; return index
  516.         jmp short search_exit ; else 
  517. search_more:
  518.         cmp byte ptr [di-1],0 ; end of string ?
  519.         jne search_next
  520.     mov ax,-1        ; not the character return -1
  521. search_exit:
  522.     leave
  523.     ret
  524. _searchchar endp
  525.  
  526. ; routine to check the filespec to insure it is valid
  527. ; it also adds a *.* on the end if it is a path (drive)
  528. ; if a \ is needed first it is also added
  529.  
  530. checkpath macro path
  531.     lea ax,path
  532.     push ax
  533.     call _checkpath
  534. endm
  535.  
  536. ifdef DEBUG            ; allow use of symdeb
  537.     public _checkpath,put_global,checkpath_exit
  538. endif                ; simplify debugging
  539.  
  540. path    equ word ptr [bp+4]
  541. pathend    equ word ptr [bp-2]
  542. _checkpath proc near        ; routine to see if input is a dir
  543.     enter 2,0        ; if it is a \ is tacked on end if needed
  544.     cld            ; left to right
  545.     mov di,path        ; point at the path
  546.     cmp byte ptr [di],0    ; is the path empty
  547.     je put_global        ; yes put on star-dot-star
  548.     searchchar path,0    ; look for end of string
  549.     add ax,path        ; point to the end of the path
  550.     mov pathend,ax        ; save the pointer to the end of the path
  551.     mov di,ax        ; use a pointer register!
  552.     cmp byte ptr [di-1],':'    ; is this just a drive spec?
  553.     je put_global        ;    then put on global search info
  554.     cmp byte ptr [di-1],'\'    ; is there a slash there already?
  555.     je put_global        ;    then put on global search info
  556.     searchchar path,'*'    ; check to see if wildcard
  557.     cmp ax,-1        ; found?
  558.     jne checkpath_exit    ;     exit routine
  559.     searchchar path,'?'    ; check to see if wildchar
  560.     cmp ax,-1        ; found?
  561.     jne checkpath_exit    ;     exit routine
  562.     mov dta.dta_attr,not is_dir    ; set attribute to known value
  563.     mov dx,path        ; what to look for
  564.     mov cx,is_dir        ; look only for a directory
  565.     mov ah,4eh        ; search for entry
  566.     int 21h
  567.     cmp dta.dta_attr,cl    ; is it the same attribute
  568.     jne checkpath_exit    ; if found
  569.         mov di,pathend    ; point to end of path
  570.         mov al,'\'
  571.         stosb        ; tack on a slash
  572. put_global:
  573.         lea si,global    ; what to append  ( di has where to put )
  574.         mov cx,len_global    ; how much to append
  575.         rep movsb        ; tack on global to end of path
  576. checkpath_exit:
  577.     leave
  578.     ret 2
  579. _checkpath endp
  580.  
  581. ; routine to copy just the path off of a string and put it in the
  582. ; destination, returning the length of the path saved
  583.  
  584. savepath macro inpath,outpath
  585.     ifnb <inpath>
  586.     lea ax,inpath
  587.     push ax
  588.     endif
  589.     ifnb <outpath>
  590.     lea ax,outpath
  591.     push ax
  592.     endif
  593.     call _savepath
  594. endm
  595.  
  596. inpath    equ word ptr [bp+6]
  597. outpath    equ word ptr [bp+4]
  598.  
  599. ifdef DEBUG            ; allow use of symdeb
  600.     public _savepath,back_not_found,save
  601. endif                ; simplify debugging
  602.  
  603. _savepath proc near        ; move just the path to destination
  604.     enter 0,0
  605.     searchchar inpath,0    ; look for end of inpath
  606.     mov bx,ax        ; save length
  607.     mov di,inpath        ; point to the path
  608.     lea di,[di+bx]        ; save pointer to last char
  609.     mov cx,bx        ; number of bytes to look at
  610.     inc cx            ; inc length of the path for # chars
  611.     std            ; right to left
  612.     mov al,'\'        ; dir char
  613.     repne scasb        ; look for
  614.     jne back_not_found    ; if found
  615.         inc cx        ;    inc length of the path
  616.         jmp short save    ; else
  617. back_not_found:
  618.         mov di,inpath    ; point to the path
  619.         lea di,[di+bx]    ; save pointer to last char
  620.         mov cx,bx        ; number of bytes to look at
  621.         inc cx        ; inc length of the path for # chars
  622.         mov al,':'        ; drive char
  623.         repne scasb        ; look for char
  624.         jne save        ; if found
  625.         inc cx        ;    inc length of the path
  626. save:    mov si,inpath        ; where get
  627.     mov di,outpath        ; where put
  628.     mov ax,cx        ; save len of path for return
  629.     cld            ; left to right
  630.     rep movsb        ; save the path
  631.     leave
  632.     ret 4
  633. _savepath endp
  634.  
  635. incchar    macro regptr            ; macro to move ptr in filename
  636.     local _inc_skip
  637.     cmp byte ptr [regptr],'.'
  638.     je _inc_skip
  639.     cmp byte ptr [regptr],0
  640.     je _inc_skip
  641.         inc regptr
  642. _inc_skip:
  643. endm
  644.  
  645. movchar    macro regptr            ; macro to move char in filename
  646.     local mov_exit
  647.     cmp byte ptr [regptr],0
  648.     je mov_exit
  649.     cmp byte ptr [regptr],'.'
  650.     je mov_exit
  651.         mov al,[regptr]
  652.         stosb
  653.         inc regptr
  654. mov_exit:
  655. endm
  656.  
  657. movall    macro regptr            ; macro to move all of filename
  658.     local mov_loop,mov_exit
  659. mov_loop:
  660.     cmp byte ptr [regptr],0
  661.     je mov_exit
  662.     cmp byte ptr [regptr],'.'
  663.     je mov_exit
  664.         mov al,[regptr]
  665.         stosb
  666.         inc regptr
  667.         jmp mov_loop
  668. mov_exit:
  669. endm
  670.  
  671. extention macro regptr            ; move to char after '.'
  672.     local ext_loop,ext_exit
  673. ext_loop:
  674.     cmp byte ptr [regptr],0
  675.     je ext_exit
  676.         cmp byte ptr [regptr-1],'.'
  677.         je ext_exit
  678.         inc regptr
  679.         jmp short ext_loop
  680. ext_exit:
  681. endm
  682.  
  683. ; this routine takes the oldname and searches the source
  684. ; creating the newname, expanding or dropping characters
  685. ; to come up the the destination name
  686.  
  687. makename macro oldname,source,newname
  688.     lea ax,oldname
  689.     push ax
  690.     lea ax,source
  691.     push ax
  692.     lea ax,newname
  693.     push ax
  694.     call _makename
  695. endm
  696.  
  697. oldname    equ word ptr [bp+8]
  698. source    equ word ptr [bp+6]
  699. newname    equ word ptr [bp+4]
  700.  
  701. ifdef DEBUG            ; allow use of symdeb
  702.     public _makename,make_loop,not_wildchar
  703.     public not_wildcard,not_period,make_exit
  704. endif                ; simplify debugging
  705.  
  706. _makename proc near        ; routine to make a destination name
  707.     enter 0,0
  708.     push source        ; address of inpath
  709.     push newname        ; address of outpath
  710.     savepath         ; parameters on stack (indirection)
  711.     mov bx,ax
  712.     mov si,source
  713.     mov di,newname
  714.     lea si,[si+bx]        ; point to the filename itself
  715.     lea di,[di+bx]        ; point to where the new name is put
  716.     mov bx,oldname        ; point to filename found
  717. make_loop:
  718.     lodsb            ; get one char in source
  719.     cmp al,'?'
  720.     jne not_wildchar    ; if question mark
  721.         movchar bx        ;     copy one char from oldname
  722.         jmp make_loop
  723. not_wildchar:
  724.     cmp al,'*'
  725.     jne not_wildcard    ; if asterick
  726.         movall bx        ;     copy rest of oldname
  727.         extention si    ;     goto extention in source
  728.         cmp byte ptr [si-1],'.' ; see if a period is needed
  729.         jne make_loop
  730.         dec si        ;     restore period if needed
  731.         jmp make_loop
  732. not_wildcard:
  733.     stosb            ; save this char in the string
  734.     cmp al,'.'
  735.     jne not_period        ; if period
  736.         extention bx    ;     goto extention in oldname
  737.         jmp make_loop
  738. not_period:
  739.     cmp al,0
  740.     je make_exit
  741.         incchar bx        ; move one in oldname
  742.         jmp make_loop
  743. make_exit:
  744.     leave
  745.     ret 6
  746. _makename endp
  747.  
  748. ; routine to return the id of the drive the filespec is on
  749. ; 0-A, 1-B, 2-C....    -1 invalid drive (device?)
  750.  
  751. drive    macro path,id
  752.     mov si,path
  753.     mov al,id
  754.     call _drive
  755. endm
  756.  
  757. ifdef DEBUG            ; allow use of symdeb
  758.     public _drive,drive_error,no_drive,drive_exit
  759. endif                ; simplify debugging
  760.  
  761. _drive    proc near
  762.     cmp al,1        ; length to ':' as parameter
  763.     jg drive_error
  764.     jl no_drive
  765.         lodsb        ; get the drive letter
  766.         cmp al,'A'        ; is it a valid char
  767.         jb drive_error
  768.         cmp al,'Z'        ; its upper case
  769.         ja drive_error
  770.         sub al,'A'    ; change into code
  771.         jmp short drive_exit
  772. no_drive:
  773.         mov ah,19h        ; get current drive id
  774.         int 21h        ; find id
  775.         jmp short drive_exit
  776. drive_error:
  777.     mov al,-1
  778. drive_exit:
  779.     ret
  780. _drive    endp
  781.  
  782. get_disk_left macro source
  783.     ifnb <source>
  784.     lea ax,source
  785.     push ax
  786.     endif
  787.     call _get_disk_left
  788. endm
  789.  
  790. ifdef DEBUG            ; allow use of symdeb
  791.     public _get_disk_left
  792. endif                ; simplify debugging
  793.  
  794. _get_disk_left proc near    ; function to find bytes left on disk
  795.     enter 0,0
  796.     searchchar path,':'    ; look to see if this is a drivespec
  797.     drive path,al        ; return the drive code if it is filespec
  798.     mov dl,al        ; find amount of space left on disk
  799.     inc dl            ; actuall drive for free space
  800.     mov ah,36h        ; get disk params
  801.     int 21h            ; call DOS
  802.     mul bx            ; sectors/cluster x # free clusters
  803.     mul cx            ; dx:ax = # bytes left on disk
  804.     leave
  805.     ret 2
  806. _get_disk_left endp
  807.  
  808. ; routine to look at the two file specs and determine whether
  809. ; we need to simple rename the files or to copy the files
  810.  
  811. findroutine macro filespec1,filespec2
  812.     lea ax,filespec1
  813.     push ax
  814.     lea ax,filespec2
  815.     push ax
  816.     call _findroutine
  817. endm
  818.  
  819. infile    equ word ptr [bp+6]    ; pointer to filespec of input file
  820. outfile    equ word ptr [bp+4]    ; pointer to filespec of output file
  821.  
  822. drive1 equ byte ptr [bp-1]    ; place to save id
  823. drive2 equ byte ptr [bp-2]    ;   "   "    "  "
  824.  
  825. ifdef DEBUG            ; allow use of symdeb
  826.     public _findroutine,use_rename,drive_length
  827.     public check_defaults,use_copy,find_exit
  828. endif                ; simplify debugging
  829.  
  830. _findroutine proc near        ; routine to check for rename or copy
  831.     enter 2,0
  832.     searchchar infile,':'    ; look for drive specification
  833.     mov drive1,al        ; save index
  834.     searchchar outfile,':'    ; look for drive specification
  835.     mov drive2,al        ; save index
  836.     cmp al,drive1        ; have same length
  837.     jne check_defaults
  838.         cmp al,-1        ; if no length
  839.         jne drive_length
  840. use_rename:    lea ax,_rename    ; all on the same drive
  841.         jmp short find_exit
  842. drive_length:            ; see if drive specifies are same?
  843.         mov cx,ax        ; number to compare
  844.         mov si,infile    ; first path
  845.         mov di,outfile    ; second path
  846.         repe cmpsb        ; compare these two drive specs
  847.         je use_rename    ; if equal goto rename
  848.         jmp short use_copy    ; else goto copy
  849. check_defaults:            ; see if refer to same
  850.     drive infile,drive1    ; find drive id for in filespec
  851.     mov drive1,al
  852.     cmp al,-1
  853.     je use_copy
  854.     drive outfile,drive2    ;   "    "    "  "  out filespec
  855.     cmp al,-1
  856.     je use_copy        ; one may be a device
  857.     cmp al,drive1
  858.     je use_rename        ; drives are the same
  859. use_copy:
  860.     lea ax,_copy
  861. find_exit:
  862.     leave
  863.     ret 4
  864. _findroutine endp
  865.  
  866. srchdir    macro dta,src,attr
  867.     setdta dta        ; use this dta
  868.     mov dx,src        ; filename to look for
  869.     ifnb <attr>
  870.     mov cx,attr        ; use this attribute
  871.     else
  872.     xor cx,cx        ; use zero
  873.     endif
  874.     mov ah,4eh        ; do a DIR search 
  875.     int 21h            ; call DOS 
  876. endm
  877.  
  878. ; routine to copy the infile to the outfile
  879.  
  880. inhandle equ word ptr [bp-2]    ; handle to input filespec
  881. outhandle equ word ptr [bp-4]    ; handle to output filespec
  882.  
  883. ifdef DEBUG            ; allow use of symdeb
  884.     public _copy,is_room,no_add,opened_infile
  885.     public opened_outfile,copy_aborted,copy_block
  886.     public copy_notokay,copy_okay,copy_exit,copy_error
  887. endif                ; simplify debugging
  888.  
  889. _copy    proc near        ; routine to copy files between disks
  890. disk_left equ word ptr [bp-8]    ; 32-bit value of bytes left on disk
  891.     enter 8,0        ; set stack w/ 2 words storage
  892.     mov outhandle,-1    ; flag that no file was open
  893.     jbrk copy_exit
  894.     push outfile        ; the parameter to get_disk_left
  895.     get_disk_left         ; set the amount of space on disk
  896.     mov word ptr disk_left,ax
  897.     mov word ptr disk_left+2,dx ; set the amount of space left
  898.     srchdir desdta,outfile ; look for srcwild using the outfile
  899.     jc no_add        ; no error then
  900.         add32 disk_left,desdta.dta_size
  901. no_add:
  902.     sub32 disk_left,dta.dta_size ; enough room on disk
  903.     jnb is_room
  904.         println no_room    ; tell user no room
  905.         mov break,1
  906.         jmp copy_exit
  907. is_room:
  908.     mov dx,infile        ; point to input filespec
  909.     mov ax,3d00h        ; open for read
  910.     int 21h            ; call DOS
  911.     jnc opened_infile
  912.         println noopenin    ; print a message
  913.         mov break,1        ; return to DOS w/ error code
  914.         jmp copy_exit
  915. opened_infile:
  916.     mov inhandle,ax        ; save the input handle
  917.     lea dx,buffer
  918. copy_block:
  919.         jbrk copy_aborted    ; if flag set abort 
  920.         mov cx,size_buffer    ; length of buffer
  921.         mov bx,inhandle    ; the input filespec
  922.         mov ah,3fh        ; read from input file
  923.         int 21h        ; call DOS
  924.         mov cx,ax        ; amount read
  925.         cmp outhandle,-1    ; if out file not opened
  926.         jne opened_outfile    ; then
  927.         push cx        ; save the length
  928.         mov dx,outfile    ; point to output filespec
  929.         xor cx,cx    ; no attribute
  930.         mov ax,3c01h    ; open for write
  931.         int 21h        ; call DOS
  932.         mov outhandle,ax ; save the output handle
  933.         lea dx,buffer    ; address of buffer
  934.         pop cx        ; restore the length to write
  935.         jnc opened_outfile
  936.             println noopenout ; print a message
  937.             mov break,1    ; signal an error
  938.             jmp short copy_exit
  939. opened_outfile:
  940.         jbrk copy_aborted    ; if flag set abort 
  941.         mov bx,outhandle    ; the output filespec
  942.         mov ah,40h        ; write to output file
  943.         int 21h        ; call DOS
  944.         jc copy_notokay
  945.         cmp ax,cx        ; write all we wanted?
  946.         je copy_okay    ; no than
  947. copy_notokay:            ; for some reason didn't work
  948.         println notransfer
  949.         mov break,1        ; signal an error
  950.         jmp short copy_error
  951. copy_okay:
  952.         cmp ax,size_buffer    ; until end of file
  953.         je copy_block
  954.     mov dx,dta.dta_date    ; get found files date
  955.     mov cx,dta.dta_time    ; get found files time
  956.     mov bx,outhandle
  957.     mov ax,5701h        ; set date:time of output file
  958.     int 21h
  959.     close outhandle        ; close output file
  960.     close inhandle        ; close input file
  961.     mov bx,infile        ; get address of infile
  962.     delete [bx]        ; delete input file bx points to it
  963.     inc num_moved        ; one filed moved
  964.     jmp short copy_exit
  965. copy_aborted:
  966.         println aborted    ; tell user about error
  967. copy_error:
  968.         close inhandle    ; close input file
  969.         close outhandle    ; close output file
  970. copy_exit:
  971.     leave            ; reset stack
  972.     ret 4            ; discard parameters and exit
  973. _copy    endp
  974.  
  975. ; routine to rename the input filespec to the output filespec
  976.  
  977. ifdef DEBUG            ; allow use of symdeb
  978.     public _rename,try_rename,rename_nogo,rename_good,rename_exit
  979. endif                ; simplify debugging
  980.  
  981. _rename    proc near        ; routine to rename the files
  982.     enter 0,0        ; set stack
  983.     test break,-1        ; see if an error occured somewhere
  984.     jz try_rename
  985.         println aborted
  986.         jmp short rename_exit
  987. try_rename:
  988.     mov dx,infile        ; point to current name
  989.     mov di,outfile        ; point to new name
  990.     mov ah,56h        ; rename function
  991.     int 21h            ; call DOS
  992.     jnc rename_good        ; simply renameing didn't work
  993.         srchdir desdta,outfile ; look for srcwild using the outfile
  994.         jc rename_nogo    ; no error then
  995.         lea si,dta.dta_reserved    ; address of the source dta
  996.         lea di,desdta.dta_reserved ; address of the destination dta
  997.         mov cx,size dta - dta_reserved ; number of bytes in dta
  998.         rep cmpsb    ; compare the two dta ( same filespecs?)
  999.         je rename_nogo    ; same then
  1000.             mov dx,outfile    ; point to destination filespec
  1001.             mov ah,41h        ; function to delete a entry
  1002.             int 21h        ; call DOS
  1003.             jnc try_rename    ; still didn't work
  1004. rename_nogo:
  1005.         println notransfer    ; tell user about this problem
  1006.         mov break,1        ; signal a error occured
  1007.         jmp short rename_exit
  1008. rename_good:
  1009.     inc num_moved        ; one file moved
  1010. rename_exit:
  1011.     leave
  1012.     ret 4
  1013. _rename    endp
  1014.  
  1015. ; macro to call the proper move procedure
  1016.  
  1017. move    macro src,des,proc
  1018.     lea ax,src
  1019.     push ax
  1020.     lea ax,des
  1021.     push ax
  1022.     call proc
  1023. endm
  1024.  
  1025. ; routine to look for all the files with the srcwild filespec
  1026. ; and move them to files with the deswild filespec
  1027.  
  1028. moveall macro routineptr
  1029.     push routineptr
  1030.     call _moveall
  1031. endm
  1032.  
  1033. ifdef DEBUG            ; allow use of symdeb
  1034.     public _moveall,first_entry,next_entry,mov_loop,moveall_exit
  1035. endif                ; simplify debugging
  1036.  
  1037. _moveall proc near        ; looks for and moves all files
  1038. srcwild    equ byte ptr [bp+86]    ; the source filespec w/global
  1039. deswild    equ byte ptr [bp+6]    ; the destination filespec w/global
  1040. mvproc    equ word ptr [bp+4]    ; routine to use in transfer
  1041. srclen    equ word ptr [bp-2]    ; length of the finame found
  1042. src    equ byte ptr [bp-82]    ; the source filespec
  1043. des     equ byte ptr [bp-162]    ; the destination filespec
  1044.     enter 162,0        ; locals = src,des,srclen
  1045.     mov num_moved,0        ; no files moved
  1046.     savepath srcwild,src    ; move the path into name
  1047.     mov srclen,ax        ; length of the path
  1048. first_entry:
  1049.     setdta dta        ; use this dta
  1050.     lea dx,srcwild        ; filename to look for
  1051.     xor cx,cx        ; use zero
  1052.     mov ah,4eh        ; do a DIR search 
  1053.     int 21h            ; call DOS 
  1054.     jnc next_entry        ; if not found
  1055.         printz srcwild    ;   print out the name looking for
  1056.         println notfile    ;   print a error message
  1057.         mov break,1        ; exit w/error
  1058.         jmp moveall_exit
  1059. next_entry:
  1060.     mov di,srclen        ; length of path
  1061.     lea di,src[di]        ; point to end of path
  1062.     lea si,dta.dta_name    ; point to filename found
  1063. mov_loop:
  1064.         lodsb        ; move file name found
  1065.         stosb        ;  to end of path
  1066.         cmp al,0        ; until a zero was moved
  1067.     jne mov_loop
  1068.     println src        ; print out the filespec that is being moved
  1069.     makename dta.dta_name,deswild,des
  1070.     move src,des,mvproc    ; move this file found
  1071.     jbrk moveall_exit
  1072.         setdta dta        ; tell dos where file info is
  1073.         mov ah,4fh        ; find next
  1074.         int 21h
  1075.         jnc next_entry    ; repeat until no more
  1076. moveall_exit:
  1077.     printmoved num_moved    ; print out the number of files moved
  1078.     leave
  1079.     ret 2
  1080. _moveall endp
  1081.  
  1082. ; this is the main program it 
  1083. ; takes over Ctrl-C
  1084. ; checks for parameters and if help is wanted
  1085. ; sets up the size of the copy buffer if it is needed
  1086. ; parses the command line for the source and destination filespecs
  1087. ; decides which routine to use
  1088. ; calls the procedure to move all of the files.
  1089. ; restores Ctrl-C
  1090. ; returns to DOS with
  1091. ;    0  :    noerror
  1092. ;    1  :    DOS error
  1093. ;    -1 :    Ctrl-C was pressed
  1094.  
  1095. ifdef DEBUG            ; allow use of symdeb
  1096.     public main,dos_good,check_help,maincont,mainexit,invalid_param
  1097.     public getparam1,getparam2
  1098. endif                ; simplify debugging
  1099.  
  1100. main    proc near        ; main procedure in program
  1101. param1    equ byte ptr [bp-80]    ; the current source filespec
  1102. param2     equ byte ptr [bp-160]    ; the current destination filespec
  1103.     enter 160,0
  1104.     mov ah,30h        ; get version number
  1105.     int 21h
  1106.     cmp ax,2        ; correct version
  1107.     jnb dos_good
  1108.         println incorrect_dos ; tell user dos is no good
  1109.         exit 1        ; return w/ error
  1110. dos_good:
  1111.     cld            ; left to right on strings
  1112.     lea si,arg        ; get ptr to command line
  1113.     xor ch,ch        ; high part of length
  1114.     mov cl,arglen        ; cx <- length of command line
  1115.     skipdelim        ; skip all delimeters
  1116.     cmp cx,0        ; are there any parameters
  1117.     jne check_help        ; if not than
  1118. invalid_param:            ;     tell user of error
  1119.         println no_param    ;     error message
  1120.         exit 1        ;     exit with error code
  1121. check_help:            ; else parameters
  1122.     cmp byte ptr [si],'?'    ; any help
  1123.     jne maincont        ; then
  1124.         cmp cx,1        ;   if only one character in buffer
  1125.         jne maincont    ;   then
  1126.         println help    ;     help message
  1127.         exit 0        ;     return to DOS
  1128. maincont:
  1129.     install_break        ; handle break key myself
  1130.     setdta dta        ; set up the dta for checkpath
  1131.     mov ax,sp        ; number of bytes in segment
  1132.     sub ax,1000h        ; set aside room for stack
  1133.     sub ax,offset buffer    ; leave the code alone
  1134.     mov size_buffer,ax    ; save the length of the buffer
  1135. getparam1: cmp cx,0
  1136.     je invalid_param    ; if no more parameters
  1137.     savenam param1        ; save the source filespec
  1138.     skipdelim        ; skip all delimeters
  1139.     checkparam param1    ; see if option
  1140.     jc getparam1
  1141. getparam2: savenam param2    ; save the destination filespec
  1142.     skipdelim        ; skip all delimeters
  1143.     checkparam param2    ; see if option
  1144.     jc getparam2
  1145.     cmp cx,0        ; if another param
  1146.     jnz invalid_param    ;    then tell user
  1147.     checkpath param1    ; fix the source if its a path
  1148.     checkpath param2    ; fix the destination if its a path
  1149.     findroutine param1,param2 ; look for the routine to use
  1150.     jbrk mainexit
  1151.         moveall ax        ; ax has pointer to function
  1152. mainexit:
  1153.     restore_break
  1154.     leave
  1155.     exit break        ; terminate process
  1156. main    endp
  1157.  
  1158. ifdef DEBUG            ; allow use of symdeb
  1159.     public buffer
  1160. endif                ; simplify debugging
  1161.  
  1162. buffer    label byte        ; this is where the buffer is
  1163.  
  1164. cseg    ends
  1165.     end entry
  1166.